iT邦幫忙

2022 iThome 鐵人賽

DAY 23
0
DevOps

一個人也能 DevOps ? 用 Angular + Spring Boot 演示專案由開發到部署系列 第 23

Day23: Jenkins Pipeline 構建,Gitlab & Harbor 串接

  • 分享至 

  • xImage
  •  

昨天我們在 Jnekins 上撰寫了我們的第一個 Pipeline,並成功地執行了起來,今天,讓我們一起串聯 Gitlab 以及 Harbor,來完成以下三個目的:

  • 將 Jenkinsfile 放置在 Gitlab Repository 內,在觸發構建時才將腳本拉取到 Jenkins 內參照執行
  • 在 Jenkins 內拉取 Gitlab 前後端的程式碼,並執行編譯與打包
  • 將編譯後的檔案製作成 Image,推送到 Harbor 內部

Pipeline Script from SCM

Pipeline Script from SCM 是將 Jenkinsfile 放置到 Gitlab Repository 內,在觸發構建時才將腳本拉取到 Jenkins 內參照執行

所以,我們在 Git Repository 創建一個檔案名為 Jenkinsfile,並將昨天的腳本內容放到裡面,隨後推送到 cct-devops 這個 Gitlab Repository 中,而之後,我們更新 Pipeline 腳本都以這一份為主,並且在修改後要推送上去。

當我們在 Jenkins color-code-tag 項目的設置內,將 Pipeline Definition 設定成 Pipeline Script from SCM 後,會看到下面多出了 SCM 的選項,我們選擇 Git 後,會看到 Repositories URLCredentials 的選項,此時我們便能將 Gti 專案的 URL 填入,同時在 Credentials 的選項下面 add 創建 Gitlab 的認證,並填入 Gitlab 的帳號與密碼。

https://ithelp.ithome.com.tw/upload/images/20221008/20132878CjwgSXbzW2.png

完成後,我們再次地按下馬上建置,便會看到 Stage View 多了一個 Declarative: Checkout SCM,表示 Jenkins 到 Gitlab 內拿到了 Jenkinsfile 並且執行了裡面的腳本。

再來,我們來讓 Jenkins 也能夠拉取後端的原始碼。

SCM for cct-java

首先到主頁面的管理 Jenkins 下,Security 內的 Manage Credentials,能夠看到我們剛才創建的 gitlab Credentials ID,我們將它複製後貼到 Jenkinsfile 內,並將參數以變數的方式抽離出來:

//被抽離的參數
def git_auth = "di8h0kfi-c312-4200-g45f-673329f9cd"
def git_address = "https://gitlab.com/Williamrightone/cct-java.git"

pipeline {

	agent any
	
	stages {
		stage('Check Java Code From Gitlab') {
			steps {
				checkout([$class: 'GitSCM', branches: [[name: "master"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_address}"]]])
					
			}
		}
	}
}

完成後按下建置,接著我們在最新的 Build 資訊側欄,點選 workspace,會看到他寫 /var/lib/jenkins/workspace/color-code-tag,點進去後,會發現我們的原始碼都被拉進 Jenkins 的 workspace 內部了。

https://ithelp.ithome.com.tw/upload/images/20221008/20132878lmo5Mun5XL.png

而 Jenkins 服務既然是架設在 Linux 機上,此時我們若連線到 192.168.1.120 內,並前往 /var/lib/jenkins/workspace/color-code-tag 路徑,即可發現我們的 Git Repository 檔案。而當我們使用 Container 架設 Jenkins 時,就會需要將 Container 內部 Jenkins workspace 的路徑映射 (mount) 到 Linux 的某個路徑下。

下一步,我們來編譯與打包 cct-java,不過這裡我們就來插播一個 Java 後端的構建 plugin jib-maven-plugin

jib-maven-plugin

jib-maven-plugin 這個套件是用於簡化 java 打包成 Image 的過程,和 Spring boot 的初衷一樣,核心就是想要讓 java 相關的業務都能達到 "Just work" 的效果,讓團隊更著重於程式碼的開發。

我們先來說明一下,原先的計畫會怎麼走:

  1. 獲取原始碼 (已達成)
  2. 下指令測試編譯與打包 mvn clean package
  3. 下指令編譯 Image docker build 192.168.1.120:9001/cct-back/cct-java:0.0.1 .
  4. 登入 Harbor,輸入 Harbor login 指令
  5. 推送 Image 到 Harbor

而 jib 的流程則僅需要再 pom 內設定要使用的 BaseImage,以及位置即可,jib 與 使用 Dockerfile 的差異可用一張圖解釋:

jib

(取自 Docker image build vs. jib)

簡言之,使用 Dockerfile 會增加許多的步驟,但是也保有夠多的彈性,而 jib 則能夠快速地為我們完成工作。

要使用 jib-maven-plugin,需要先在 pom 裡面引入 dependancy,並且設置:

	<groupId>com.william</groupId>
	<artifactId>color-code-tag-back</artifactId>
	<version>0.0.2</version>
	<name>color-code-tag-back</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<java.version>11</java.version>
		<docker.image.prefix>192.168.1.120:9001/cct-java/cct-back</docker.image.prefix>
		<jib-maven-plugin.version>2.2.0</jib-maven-plugin.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>

			<plugin>
				<artifactId>jib-maven-plugin</artifactId>
				<groupId>com.google.cloud.tools</groupId>
				<version>${jib-maven-plugin.version}</version>
				<configuration>
					<from>
						<image>registry.access.redhat.com/ubi8/openjdk-11-runtime</image>
					</from>
					<to>
						<image>${docker.image.prefix}:${project.version}</image>
					</to>
					<allowInsecureRegistries>true</allowInsecureRegistries>
				</configuration>
			</plugin>
		</plugins>
	</build>

這樣,在匯出時,則會 >${docker.image.prefix}:${project.version} 創建出 192.168.1.120:9001/cct-java/cct-back:0.0.2了;另外,我們也將 BaseImage 更改為 redhat 的官方 Image。

接著我們要設定 Harbor 的 Credentials,此時我們可以使用原先創建的 william,也可以到 Harbor 項目內創立機器人帳戶,這裡選用機器人帳戶,我們先到 Harbor 的項目內選擇機器人帳戶。

https://ithelp.ithome.com.tw/upload/images/20221008/20132878kmnhmL1LJv.png

再點選 添加機器人帳戶 ,設定時可以將調整其權限。

https://ithelp.ithome.com.tw/upload/images/20221008/20132878e4W544GKwo.png

點選後,我們有一次能夠保存 token 的機會,他相當於是機器人帳號的密碼。拿到和我們可以到 Jenkins 內的管理選項,利用創建的機器人帳號與密碼,新增一個 Harbor 的 Credential。

Harbor 串接

再來我們更新 Jenkinsfile,在這裡我們可以使用 mvn package jib:dockerBuild 執行 Image 的建立。這裡我們將 jib Image 製作與推送 這個 Stage 加入,並用上剛才創建的 harbor Credential。

//被抽離的參數
def git_auth = "dbe4cf79-ca87-4200-a6d8-6883b895ce3c"
def git_address = "https://gitlab.com/Williamrightone/cct-java.git"
def harbor_auth = "a372743f-7400-492f-8893-0d50b1a79287"

pipeline {
	agent any
	stages {
		stage('Check Java Code From Gitlab') {
			steps {
				checkout([$class: 'GitSCM', branches: [[name: "master"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_address}"]]])
			}
		}

		stage('jib Image 製作與推送') {
             steps {				
				script{
					withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'harborPasswd', usernameVariable: 'haborUser')]) {
							sh '''
							mvn compile jib:build \
							-DsendCredentialsOverHttp=true \
							-Djib.to.auth.username=${haborUser} \
							-Djib.to.auth.password=${harborPasswd}
							'''
							}	
						}
					}					
				}
			}
}

從 Stage View 可以看到建構與打包的時間是 1min 57s,而 Harbor 內也有了 0.0.2 版本的 Tags 了。

https://ithelp.ithome.com.tw/upload/images/20221008/20132878pwTZtpe5Do.png

看看 Harbor

https://ithelp.ithome.com.tw/upload/images/20221008/20132878KZe25AzXnt.png

Webhook

前端的打包就需要用原來的方法了,同時因為觸發構建的將會是另外的一個 Git Repository 的更新,因此我們要為 ctt 的前端也開一個 Pipeline 項目,並且也要為 Harbor cct-web 建立機器人帳號,並設定 credentials :

//被抽離的參數
def git_auth = "dbe4cf79-ca87-4200-a6d8-6883b895ce3c"
def git_address = "https://gitlab.com/Williamrightone/cct-web.git"
def harbor_auth = "d597f032-e903-4d05-8c07-df27b8ff86eb"

pipeline {

	agent any
	
	stages {
		stage('Check Web Code From Gitlab') {
			steps {
				checkout([$class: 'GitSCM', branches: [[name: "master"]], extensions: [], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_address}"]]])
					
			}
		}

		stage('Docker Image 製作與推送') {
         steps {				
		  script{
		   withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'harborPasswd', usernameVariable: 'haborUser')]) {
									
			sh 'docker build -t 192.168.1.120:9001/cct-web/cct-front:0.0.2 .'
			sh 'docker login -u ${haborUser} -p ${harborPasswd} http://192.168.1.120:9001'
			sh 'docker push 192.168.1.120:9001/cct-web/cct-front:0.0.2 '
			sh 'docker rmi 192.168.1.120:9001/cct-web/cct-front:0.0.2 '
						    
				}	
			   }
             }					
			}	
		}
}

完成後建置,可以 Jenkins 則會拉取 Angular 並且打包與推送了(其實我們的前端也能夠使用相同的方式打包與傳送)。

https://ithelp.ithome.com.tw/upload/images/20221008/201328788e1Fu8w915.png

到這裡,我們已經利用 Jenkins 為我們完成了自動的整合與交付 (Integration & Delivery),明天,我們再讓 Jenkins 能夠遠端連線到 SIT 機 (192.168.1.188 那台),並且將 Image 拉進來部署;以及為 Jenkins 掛上 Webhooks,讓我們推送 code 到 Gitlab 時,會自動的觸發 Pipeline。

今日總結

關於 Jenkinsfile 可以使用 devops 的分支進行管理,讓不同分之對應不同的 Jenkins job。

今天我們完成了前後端的原始碼拉取到 Image 的交付,總算是快要完成 CI/CD 的建置了。原本以為雙十節會有比較多時間寫,結果還是從下午寫到了傍晚...。


上一篇
Day:22 Jenkins 安裝與基礎設置
下一篇
Day24: Jenkins 部署,Publish Over SSH
系列文
一個人也能 DevOps ? 用 Angular + Spring Boot 演示專案由開發到部署30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言